with Ada.Strings.Unbounded; use Ada.Strings.Unbounded;
with Ada.Text_IO; use Ada.Text_IO;
with Tipus; use Tipus;


package body Parser is

   File_Name_Length: Integer;
   File_Name: Unbounded_String := Null_Unbounded_String;
   File_Name_Without_Ext: Unbounded_String := Null_Unbounded_String;




   ----------------------------------------------------
   -- Converts an array of numbers into an Integer
   ----------------------------------------------------
   function Array_To_Int (PIA: in PTR_Integer_Array; final_position: Integer) return Integer is
      i, j, pow, num: Integer := 0;
   begin
      i:=final_Position;
      while i>=1 loop
         pow:=10**j;
         num:=num+PIA(i)*pow;
         i:=i-1;
         j:=j+1;
      end loop;
      return num;
   end Array_To_Int;

   ------------------------------------------------------------------------
   --Reads a number from a line starting from a position without blanks
   ------------------------------------------------------------------------
   procedure Read_Number (Long_Line: in String; len: in Integer; first_pos: in Integer; final_pos: out Integer; Numbers_Array: in PTR_Integer_Array; numbers_size: out Integer) is
      i,j,n: Integer;
      c: Character;
      ok: boolean;
   begin
      i:= first_pos; --first position to start reading the number
      j:=1;
      n:=0;
      ok:=true;
      while i<=len and ok loop
         c:=Long_Line(i);
         if c/=' ' then
            --Convert char to integer and keep it in an array
            n:=CHARACTER'POS(C)-CHARACTER'POS('0');
            Numbers_array(j):=n;
            j:=j+1;
         else
            ok:=false;
         end if;
         i:=i+1;
      end loop;
      numbers_size:=j-1;
      final_pos:=i-1;
   end Read_Number;

   -------------------------------------------------------------------------------------
   -- Reads a number in a line from a certain position 'eating' all the blanks before
   -------------------------------------------------------------------------------------
   procedure Read_Blanks_Number (Long_Line: in String; len: in Integer; first_pos: in Integer; final_pos: out Integer; Numbers_Array: in PTR_Integer_Array; numbers_size: out Integer) is
      i,j,n: Integer;
      c: Character;
   begin
      i:= first_pos; --first position to start reading the number
      j:=0;
      n:=0;
      while i<=len loop
         c:=Long_Line(i);
         if c/=' ' then
            --Convert char to integer and keep it in an array
            n:=CHARACTER'POS(C)-CHARACTER'POS('0');
            j:=j+1;
            Numbers_array(j):=n;
         end if;
         i:=i+1;
      end loop;
      numbers_size:=j;
      final_pos:=i-1;
   end Read_Blanks_Number;


   --------------------------------------------
   -- Method to set the filename to read from
   --------------------------------------------
   procedure Set_File_Name(Name: in String; name_length: in Positive) is
   begin
      File_Name:=To_Unbounded_String(Name);
      File_Name_length:=name_length;
      File_Name_Without_Ext:=To_Unbounded_String(Name(Name'First..File_Name_length-4));
   end Set_File_Name;

   --------------------------------------------------------------
   -- Method to read from a Pajek File and store the information
   --------------------------------------------------------------
  procedure Read_Pajek_File(Vector: in out PTR_Array_Nodes) is

      Pajek_File: File_Type;
      C: Character;
      I, Len, Nv: Integer;
     Id_Node1, Id_Node2 : Integer;
      first_position, final_position, numbers_size: Integer:=1;
      Numbers: PTR_Integer_Array;
      Num_Vertices: Integer;
      Long_Line: String(1..100);

   begin
      Numbers:= new Integer_Array(1..20);

      --Open Pajek File
      Open(Pajek_File, In_File, To_String(File_Name));

      --Read first line and get num_Vertices
      Get_Line(Pajek_File, Long_Line,len);
      first_position:=10; --Where blanks start after the word "*Vertices"

      --We have to read the characters of the number of vertices and store it in an array
      Read_Blanks_Number(Long_Line,len,first_position,final_position,Numbers,numbers_Size);
      Num_Vertices:=Array_To_Int(Numbers,numbers_size); --now we have the integer

      --Now that we know the size, we can create the array to keep all the information read
      Vector := new Array_Nodes(1..Num_Vertices);

      --Clean the Long_Line with blanks
      for x in 1..Long_Line'Length loop
         Long_Line(x):=' ';
      end loop;

      --Read the vertices information: only id and name
      Nv:=1;

      while nv <= num_Vertices loop
         --Reset before using it again
         for x in 1..len loop
            Long_Line(x):=' ';
         end loop;

         Get_Line(Pajek_File, Long_Line, len);
         first_position := 1;
         --Read the number that identifies each vertex
         Read_Number(Long_Line, Len, First_Position, Final_Position, Numbers, Numbers_Size);
         Vector(nv).id := Array_To_Int(Numbers, numbers_size);
         --Aprofito per inicialitzar la llista de connexions
         Int_Linked_Lists.Initialize(Vector(nv).Llista_Connexions);

         i:=final_position;
         c:=Long_Line(i); --next char
         while c = ' ' loop --eat the blanks
            i:=i+1;
            c:=Long_Line(i);
         end loop;
         --name goes from position 'i' until next blank
         while Long_Line(i) /= ' ' loop
            --Append(IVA(nv).name, Long_Line(i));
            Append(Vector(nv).Nom, Long_Line(i));
            i:=i+1;
         end loop;
         Vector(nv).id := nv;
         nv:=nv+1;
      end loop;


      --Read edges line
      Get_Line(Pajek_File, Long_Line,len);

      --Clean the Long_Line with blanks
      for x in 1..Long_Line'Length loop
         Long_Line(x):=' ';
      end loop;

      --Read the list of edges
      while (not End_Of_File(Pajek_File)) loop
         Get_Line(Pajek_File, Long_Line,len);
         first_position:=1;
         Read_Number(Long_Line,len,first_position,final_position,Numbers,numbers_size);
         Id_node1 := Array_To_Int(Numbers, numbers_size);
         first_position:=final_position+1;
         Read_Number(Long_Line,len,first_position,final_position,Numbers,numbers_size);
         Id_node2 := Array_To_Int(Numbers, Numbers_Size);
 
         Int_Linked_Lists.Add_Last(Id_Node2, Vector(Id_Node1).Llista_Connexions);
         Int_Linked_Lists.Add_Last(Id_Node1, Vector(Id_Node2).Llista_Connexions);
         Vector(Id_Node1).Num_Connexions := Vector(Id_Node1).Num_Connexions + 1;
         Vector(Id_Node2).Num_Connexions := Vector(Id_Node2).Num_Connexions + 1;
      end loop;
      
    end Read_Pajek_File;
    

end Parser;
